﻿using System;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Media;
using Bling.DSL;
using Bling.WPF;
using Bling.Animation;

namespace Bling.Tutorial {
  public class Tweens : Canvas, CanStart {
    private readonly LabelSliderBl slider;
    public Tweens() {
      CanvasBl canvas = this;
      var map = new Dictionary<string, Func<DoubleBl, DoubleBl.OutInBl>>();
      map["Sine"] = t => t.Ease.Sine;
      map["Expo"] = t => t.Ease.Expo;
      map["Quad"] = t => t.Ease.Quad;
      map["Cubic"] = t => t.Ease.Cubic;
      map["Quatric"] = t => t.Ease.Quatric;
      map["Quintic"] = t => t.Ease.Quintic;
      map["Elastic"] = t => t.Ease.Elastic;
      map["Circ"   ] = t => t.Ease.Circ;
      map["Bounce" ] = t => t.Ease.Bounce;
      map["Back"   ] = t => t.Ease.Back;

      slider = new LabelSliderBl(canvas) {
        RightBottom = canvas.Size, Width = canvas.Width,
        Minimum = 0, Maximum = 1, ZIndex = 1, LabelName = "Progress"
      };
      var InOut = new RadioButtonBl(canvas) {
        LeftBottom = slider.LeftTop, Content = "InOut", GroupName = "XXX",
      };
      var OutIn = new RadioButtonBl(canvas) {
        LeftBottom = InOut.LeftTop, Content = "OutIn", GroupName = "XXX",
      };
      var In = new RadioButtonBl(canvas) {
        LeftBottom = OutIn.LeftTop, Content = "In", GroupName = "XXX",
      };
      var Out = new RadioButtonBl(canvas) {
        LeftBottom = In.LeftTop, Content = "Out", GroupName = "XXX", IsChecked = true,
      };
      Func<DoubleBl.OutInBl, DoubleBl> F = (ease) => {
        return Out.IsChecked.Condition(ease.Out, In.IsChecked.Condition(ease.In, OutIn.IsChecked.Condition(ease.OutIn, ease.InOut)));
      };
      Func<DoubleBl.OutInBl, DoubleBl> G = (ease) => {
        if (Out.IsChecked.CurrentValue) return ease.Out;
        if (In.IsChecked.CurrentValue) return ease.In;
        if (InOut.IsChecked.CurrentValue) return ease.InOut;
        if (OutIn.IsChecked.CurrentValue) return ease.OutIn;
        throw new NotSupportedException();
      };
      DoubleBl Top = 0;
      Color b0 = Colors.Red;
      Color b1 = Colors.Black;
      var image = new ImageBl(canvas) {
        Size = canvas.Size, ZIndex = 0,
        LeftTop = new PointBl(0, 0),
        Source = Properties.Resources.Autumn,
      };
      foreach (var v in map) {
        var vv = v.Value;
        var lerp = F(v.Value(slider.Value));
        var background = new SolidColorBrushBl() { Color = lerp.Lerp(b0.Bl(), b1.Bl()) };
        var foreground = new SolidColorBrushBl() { Color = lerp.Lerp(b1.Bl(), b0.Bl()) };

        var lbl = new LabelBl(canvas) {
          Top = Top, ZIndex = 1,
          Content = v.Key, Background = background, Foreground = foreground,
          Font = { Size = 20, Weight = FontWeights.SemiBold },
          OnMouseEnter = (x,y) => { // Just for fun.
            image.Effect.Custom = (input, uv) => {
              var cp = new PointBl(0.5, 0.5);

              var dist = (uv - cp).Length / (cp.Length);
              dist = 1d - dist;

              var lerp0 = (G(vv(dist * slider.Value)));
              uv = (uv + new PointBl(lerp0,lerp0));
              uv = new PointBl(uv.X % 1, uv.Y % 1);
              return input[uv];
            };
            return true;
          },
        };
        Top = lbl.Bottom;
        lbl.Left =  lerp * (canvas.Width - lbl.Width);

        var c = b0;
        b0 = b1;
        b1 = c;
      }
    }
    public void Start() {
      slider.Value = 0;
      slider.Value.Animate.AutoReverse().Forever().Duration(1000).To = 1;
    }
    public void Stop() {
      slider.Value.Stop(true);
    }
  }
}
